package org.pentaho.cubic.login.client;

import java.util.Date;

import org.pentaho.cubic.login.client.ICubicLoginServiceAsync;
import org.pentaho.cubic.login.client.ICubicLoginService;
import org.pentaho.cubic.login.shared.FieldVerifier;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class CubicLogin implements EntryPoint {

	private static ICubicLoginServiceAsync SERVICE;

	static {
		SERVICE = (ICubicLoginServiceAsync) GWT.create(ICubicLoginService.class);
		ServiceDefTarget endpoint = (ServiceDefTarget) SERVICE;
		String moduleRelativeURL = GWT.getModuleBaseURL() + "CubicLoginService"; //$NON-NLS-1$
		endpoint.setServiceEntryPoint(moduleRelativeURL);
	}

	public void onModuleLoad() {
		final VerticalPanel loginPanel = new VerticalPanel();
		
		
		final Label titleLabel = new Label("Business Intelligence for Student Performance Analysis");
		final Label subtitleLabel = new Label("ระบบสารสนเทศเพื่อการวิเคราะห์สมรรถภาพของนักศึกษา");
		final FlexTable loginTable = new FlexTable();
		final Label nameLabel = new Label("Username");
		final Label passwordLabel = new Label("Password");		
		final TextBox usernameField = new TextBox();
		final PasswordTextBox passwordField = new PasswordTextBox();	
		final CheckBox rememberCheck = new CheckBox("Remember me on this computer");
		final Button loginButton = new Button("Login");
		
		final Label errorLabel = new Label();
		

		loginPanel.addStyleName("loginPanel");
		titleLabel.addStyleName("titleLabel");
		subtitleLabel.addStyleName("subtitleLabel");
		//errorLabel.addStyleName("errorLabel");
		loginTable.addStyleName("loginTable");
		loginButton.addStyleName("loginButton");
		
		loginTable.setWidget(1, 0, nameLabel);
		loginTable.setWidget(1, 1, usernameField);
		loginTable.setWidget(2, 0, passwordLabel);
		loginTable.setWidget(2, 1, passwordField);
		loginTable.setWidget(3, 0, rememberCheck);
		loginTable.getFlexCellFormatter().setColSpan(3, 0, 2);
		loginTable.setWidget(4, 0, loginButton);
		loginTable.getFlexCellFormatter().setColSpan(4, 0, 2);
		
		loginPanel.add(titleLabel);
		loginPanel.add(subtitleLabel);
		loginPanel.add(errorLabel);
		loginPanel.add(loginTable);
		RootPanel.get().add(loginPanel);
		
		
		// Focus the cursor on the name field when the app loads
		usernameField.setFocus(true);
		usernameField.selectAll();

		class LoginHandler implements ClickHandler, KeyUpHandler {

		    Timer t = new Timer() {
		        public void run() {
					errorLabel.removeStyleName("errorLabel");
					errorLabel.setText("");
		        }
		    };
		    
			public void onClick(ClickEvent event) {
				Authenticate();
			}

			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					Authenticate();
				}
			}

			private void Authenticate() {
				// Verify
				errorLabel.setText("");
				String textToServer = usernameField.getText();

				if (!FieldVerifier.isValidName(textToServer)) {
					errorLabel.setStyleName("errorLabel");
					errorLabel.setText("Please check your username and password");
					t.schedule(2000);
					return;
				}

				// Prepare
				String path = Window.Location.getPath();
				if (!path.endsWith("/")) { //$NON-NLS-1$
					path = path.substring(0, path.lastIndexOf("/") + 1); //$NON-NLS-1$
				}
				RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, path + "j_spring_security_check"); //$NON-NLS-1$
				builder.setHeader("Content-Type", "application/x-www-form-urlencoded"); //$NON-NLS-1$ //$NON-NLS-2$

				// Callback
				RequestCallback callback = new RequestCallback() {

					public void onError(Request request, Throwable exception) {
						errorLabel.setStyleName("errorLabel");
						errorLabel.setText("Error: " + exception.getMessage());
						loginButton.setEnabled(true);
						t.schedule(2000);
						return;
					}

					public void onResponseReceived(Request request, Response response) {
						final AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {

							public void onSuccess(Boolean result) {

								if (result) {
									long year = 1000 * 60 * 60 * 24 * 365;
									// one year into the future
									Date expirationDate = new Date(System.currentTimeMillis() + year);
									Cookies.setCookie("loginNewWindowChecked", "" + false, expirationDate); //$NON-NLS-1$ //$NON-NLS-2$
									errorLabel.setStyleName("successLabel");
									errorLabel.setText("Authenticated");
									//Window.alert(Window.Location.getPath());
									Window.Location.replace(Window.Location.getPath().replace("Login", "CubicHome")); //$NON-NLS-1$ //$NON-NLS-2$
									//Window.alert("OK");
								} else {
									errorLabel.setStyleName("errorLabel");
									errorLabel.setText("Authentication Failed: Check Username or Password ");
									loginButton.setEnabled(true);
									t.schedule(2000);
									return;
								}
							}

							public void onFailure(final Throwable caught) {
								errorLabel.setStyleName("errorLabel");
								errorLabel.setText("Authentication Failed: " + caught.getMessage());
								loginButton.setEnabled(true);
								t.schedule(2000);
								return;
							}
						};
						SERVICE.isAuthenticated(callback);
					}
				};

				// Send Request
				loginButton.setEnabled(false);
				try {
					String username = usernameField.getText();
					String password = passwordField.getText();
					builder.sendRequest("j_username=" + URL.encodeComponent(username) + "&j_password=" + URL.encodeComponent(password), callback); //$NON-NLS-1$ //$NON-NLS-2$
				} catch (RequestException e) {
					e.printStackTrace();
				}
			}
		}

		// Add a handler to send the name to the server
		LoginHandler handler = new LoginHandler();
		loginButton.addClickHandler(handler);
		passwordField.addKeyUpHandler(handler);
	}
}
